﻿using DotNetStar.TheKing.Infrastructure;
using SDDP;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;

namespace DotNetStar.TheKing.Domain
{
    /// <summary>
    /// 内容
    /// </summary>
    [Table("Contents")]
    public class Content : IEntity<long>
    {
        /// <summary>
        /// 自增
        /// </summary>
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long Id { get; set; }

        /// <summary>
        /// 分类Id
        /// </summary>
        public int? CategoryId { get; set; }
        
        /// <summary>
        /// 频道。
        /// </summary>
        public Channels Channel { get; set; }

        /// <summary>
        /// 标题
        /// </summary>
        [StringLength(60)]
        public string Subject { get; set; }

        /// <summary>
        /// 正文
        /// </summary>
        [MaxLength]
        public string Body { get; set; }

        /// <summary>
        /// 作者Id。
        /// </summary>
        public long AuthorId { get;  set; }

        ///// <summary>
        ///// 作者昵称
        ///// </summary>
        //[Required, StringLength(30)]
        //[Obsolete]
        //public string AuthorUserName { get; private set; }

        /// <summary>
        /// 发布时间
        /// </summary>
        public DateTime PostedTime { get; set; } = DateTime.Now;

        /// <summary>
        /// 状态
        /// </summary>
        public ContentStatus Status { get;  set; }

        /// <summary>
        /// 访问数
        /// </summary>
        public int VisitNum { get; set; }

        /// <summary>
        /// 点攒数
        /// </summary>
        public int LikeNum { get; set; }
        /// <summary>
        /// 是否原创。
        /// </summary>
        public bool IsOriginal { get; set; }

        /// <summary>
        /// 自定义链接。
        /// </summary>
        /// <remarks>
        /// <see cref="Channels.Video"/> 则是视频链接
        /// 其他则是外链
        /// </remarks>
        [StringLength(150)]
        public string Url { get; set; }

        /// <summary>
        /// 付费状况。
        /// </summary>
        /// <remarks>
        /// 问答-悬赏积分。
        /// 其他-付费积分
        /// </remarks>
        public int? Cost { get;  set; }

        /// <summary>
        /// 是否封锁评论。
        /// </summary>
        public bool IsLockComment { get;  set; }

        /// <summary>
        /// 最佳答案
        /// </summary>
        public Guid? BestCommentId { get;  set; }

        public int OrderNo { get;  set; }

        /// <summary>
        /// 是否私密
        /// </summary>
        public bool IsSecret { get; set; }
        /// <summary>
        /// 是否只允许邀请用户查看
        /// </summary>
        public bool OnlyInviteUser { get; set; }


        #region 领域方法
        /// <summary>
        /// 保存为草稿。
        /// </summary>
        public void SaveDraft() => this.Status = ContentStatus.Draft;

        /// <summary>
        /// 待审核
        /// </summary>
        public void PendingAudit() => this.Status = ContentStatus.Auditing;

        /// <summary>
        /// 审核通过
        /// </summary>
        public void Audited() => this.Status = ContentStatus.Normal;

        /// <summary>
        /// 屏蔽访问。
        /// </summary>
        public void Band() => this.Status = ContentStatus.Forbidden;

        /// <summary>
        /// 设置作者
        /// </summary>
        /// <param name="user">The user.</param>
        public void SetAuthor(User user)
        {
            this.AuthorId = user.Id;
        }

        /// <summary>
        /// 增加访问数
        /// </summary>
        /// <param name="step">偏移量</param>
        public void IncreaseVisitNum(int step = 1) => this.VisitNum += step;


        /// <summary>
        /// 不允许评论
        /// </summary>
        public void LockComment() => this.IsLockComment = true;
        /// <summary>
        /// 允许评论
        /// </summary>
        public void UnlockComment() => this.IsLockComment = false;

        /// <summary>
        /// 消费金币数
        /// </summary>
        /// <param name="cost">The cost.</param>
        public void SetCost(int? cost)
        {
            if (cost.HasValue && cost.Value > 0)
            {
                this.Cost = cost;
            }
        }
        /// <summary>
        /// 增加点攒数
        /// </summary>
        /// <param name="like">The like.</param>
        public void IncreaseLike(int like = 1) => this.LikeNum += like;
        /// <summary>
        /// 减少点攒数。
        /// </summary>
        /// <param name="like">The like.</param>
        public void DecreseLike(int like = 1)
        {
            if (this.LikeNum > 0)
            {
                this.LikeNum -= like;
            }
        }

        /// <summary>
        /// 设置最佳评论。仅问答有效。
        /// </summary>
        /// <param name="commentId"></param>
        public void SetBestComment(Guid commentId)
        {
            this.BestCommentId = commentId;
            this.LockComment();
        }

        /// <summary>
        /// 表示当前帖子是否免费
        /// </summary>
        /// <returns></returns>
        public bool IsFree() => !this.Cost.HasValue || this.Cost.Value == 0;

        public IEnumerable<string> GetTagNames() => ContentTags.Select(m => m.Name);

        public bool IsAsk => this.Channel == Channels.Ask;
        public bool IsCode => this.Channel == Channels.Code;
        public bool IsContent => this.Channel == Channels.Content;

        public bool IsVideo => this.Channel == Channels.Video;

        public bool IsEducation => this.Channel == Channels.Education;

        
        #endregion

        #region 其他成员
        /// <summary>
        /// 内容缓存的键
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="page"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static string GetContentsCacheKey(Channels? channel, int page, long? userId = default(long?))
    => "content-channel:{0}-page:{1}{2}".StringFormat(channel, page, userId.HasValue ? $"user:{userId.Value}" : string.Empty);

        public static string GetContentsCacheKey(Channels channel, int? categoryId = default(int?))
    => "content-channel:{0}{1}".StringFormat(channel, categoryId.HasValue ? $"category-{categoryId.Value}" : string.Empty);

        /// <summary>
        /// 缓存键
        /// </summary>
        /// <param name="contentId"></param>
        /// <returns></returns>
        public static string GetContentCacheKey(long contentId) => $"content-{contentId}";
        #endregion

        #region 导航属性
        [NotMapped]
        public Category Category { get; set; }
        [NotMapped]
        public User Author { get; set; }

        [NotMapped]
        public IEnumerable<Tag> ContentTags { get; set; } = new HashSet<Tag>();

        /// <summary>
        /// 当前帖子的总评论数
        /// </summary>
        [NotMapped]
        public int CommentCount { get; set; }

        /// <summary>
        /// 邀请用户集合
        /// </summary>
        [NotMapped]
        public IEnumerable<User> InvitedUsers { get; set; }
        #endregion
    }


}
